package com.cloudinnov.logic.impl;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import com.cloudinnov.dao.InitDataBaseDao;
import com.cloudinnov.logic.CameraControlLogic;
import com.cloudinnov.logic.GlobalInitLogic;
import com.cloudinnov.logic.LightDetectLogic;
import com.cloudinnov.model.LightDetect;
import com.cloudinnov.task.ElectricInformationScanJob;
import com.cloudinnov.task.ElectricMonitor;
import com.cloudinnov.task.SchduleScanJob;
import com.cloudinnov.utils.CarDetectorServerWP;
import com.cloudinnov.utils.CommonUtils;
import com.cloudinnov.utils.EmergecyPhoneServer;
import com.cloudinnov.utils.FireAlarmServer;
import com.cloudinnov.utils.LightDetectorClient;
import com.cloudinnov.utils.MultiThreadServer;
import com.cloudinnov.utils.PropertiesUtils;
import com.hjzk.fire.FireHandler;
import com.mysql.jdbc.Connection;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
 

/** 
 * @author chengning
 * @date 2017年9月12日上午11:13:59
 * @email ningcheng@cloudinnov.com
 * @remark
 * @version 
 */
@Service
public class GlobalInitLogicImpl implements GlobalInitLogic  {
    
    private static final Logger LOG = LoggerFactory.getLogger(GlobalInitLogicImpl.class);
    private static final String RESOURCE_CODE = "RE";
    private static final String RESOURCE_NAME = "resources";
    private static final String ROLE_CODE = "RO";
    private static final String ROLE_NAME = "role";
    private static final String USER_CODE = "US";
    private static final String USER_NAME = "user";
    private static final String CUSTOMER_CODE = "CU";
    private static final String CUSTOMER_NAME = "customer";

    public static boolean EMERGECY_PHONE_START_UP = false;
    public static boolean FIRE_CRE_START_UP = false;
    public static boolean CAR_TCP_START_UP = false;
    public static boolean INIT_ALLSCREEN_START_UP = false;
    public static boolean INIT_DATABASE_START_UP = false;
    public static final String EMERGECY_PHONE_THREAD_ALIAS = "emergecyThread";
    private static final String EMERGECY_PHONE_THREAD_NAME = "紧急电话后台线程";
    public static final String FIRE_CRE_THREAD_ALIAS = "fireCREThread";
    private static final String FIRE_CRE_THREAD_NAME = "火灾报警器后台线程";
    public static final String CAR_TCP_THREAD_ALIAS = "carTcpThread";
    private static final String CAR_TCP_THREAD_NAME = "车检仪后台线程";
    public static final String INIT_ALLSCREEN_THREAD_ALIAS = "allScreenThread";
    private static final String INIT_ALLSCREEN_THREAD_NAME = "大屏后台线程";
    public static final String INIT_DATABASE_THREAD_ALIAS = "initDataBaseThread";
    private static final String INIT_DATABASE_THREAD_NAME = "数据库后台线程";
    private static final String INIT_LIGHT_THREAD_NAME="能见度检测器后台线程";
    private static final String INIT_LIGHT_THREAD_ALIAS="initLightTcpThead";
    private static final String INIT_ND_FIRE_DETECTOR_NAME="内邓火灾报警器";
    private static final String INIT_ND_FIRE_DETECTOR_ALIAS="initNDDetectThread";
    private static final String INIT_PLAN_SCAN_NAME="群控联动扫描线程";
    private static final String INIT_PLAN_SCAN_ALIAS="initPlanDetectThread";
    
    
    @Autowired
    private JedisPool redisPool;
    @Autowired
    private InitDataBaseDao initDataBaseDao;
    @Autowired
    private AmqpTemplate callTemplate;
    @Autowired
    private AmqpTemplate fireTemplate;
    @Autowired
    private CameraControlLogic cameraControlLogic;
	@Autowired
	LightDetectLogic lightDetectLogic;
    
    
    public void setRedisPool(JedisPool redisPool) {
        this.redisPool = redisPool;
    }
    public void setCallTemplate(AmqpTemplate callTemplate) {
        this.callTemplate = callTemplate;
    }
    public void setFireTemplate(AmqpTemplate fireTemplate) {
        this.fireTemplate = fireTemplate;
    }
    
    /** 
    * @Fields BACKGROUND_THREADS : 后台所有线程
    */ 
    static Map<String, Thread> BACKGROUND_THREADS = new HashMap<>();
    
    @Override
    public void initEmergecyPhoneRevice() {
        Thread emergecyThread = new Thread(EMERGECY_PHONE_THREAD_NAME) {
            public void run() {
                EmergecyPhoneServer emercyPhoneServer = new EmergecyPhoneServer(callTemplate);
                emercyPhoneServer.startListen(PropertiesUtils.findPropertiesKey("emergencyCallServer.hostname"),
                        Integer.parseInt(PropertiesUtils.findPropertiesKey("emergencyCallServer.port")));
            };
        };
        emergecyThread.start();
        BACKGROUND_THREADS.put(EMERGECY_PHONE_THREAD_ALIAS, emergecyThread);
    }
    
    @Override
    public void initFireCRERevice() {
        Thread fireCREThread =  new Thread(FIRE_CRE_THREAD_NAME) {
            public void run() {
                FireAlarmServer tcpServer = new FireAlarmServer(fireTemplate);
                tcpServer.startFireSystem(PropertiesUtils.findPropertiesKey("fireAlarmCRTServer.port"));
            }
        };
        fireCREThread.start();
        BACKGROUND_THREADS.put(FIRE_CRE_THREAD_ALIAS, fireCREThread);
    }
    
    @Override
	public void initLightTcpService() {
	 
		LOG.info("能见度检测器准备启动------------------------------------------------------------");
		try {
			final List<LightDetect> lightDetectIpInfo = lightDetectLogic.lightDetectIpInfo();
			int port=Integer.parseInt(PropertiesUtils.findPropertiesKey("light.detector.tcp.port"));
			Thread lightTcpThread= new Thread(INIT_LIGHT_THREAD_NAME){
				public void run(){
					for (int i = 0; i < lightDetectIpInfo.size(); i++) {
						LOG.info("能见度检测器初始化------------------------------------------------------------");
						 LightDetectorClient lightDetectorClient=new LightDetectorClient(lightDetectIpInfo.get(i).getValue(), port, lightDetectIpInfo.get(i).getEquipmentCode());
						 lightDetectorClient.start();
					}
				}
			};
			lightTcpThread.start();
			BACKGROUND_THREADS.put(INIT_LIGHT_THREAD_ALIAS, lightTcpThread);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    
    @Override
    public void initCarTcpRevice() {
    	 
        Thread carTcpThread = new Thread(CAR_TCP_THREAD_NAME) {
            public void run() {
                try {
                    try {
                    	if(PropertiesUtils.findPropertiesKey("project.name").equals("cqew")) {
                    		new MultiThreadServer(Integer.parseInt(PropertiesUtils.findPropertiesKey("car.detector.tcp.port")))
					        .service();
                    	}else if (PropertiesUtils.findPropertiesKey("project.name").equals("wanping")) {
                    		new CarDetectorServerWP("192.168.22.234", 961 ).startConnectService();
//                    		new CarDetectorServerWP("192.168.22.234", 962 ).startConnectService();
//                    		new CarDetectorServerWP("192.168.22.234", 963 ).startConnectService();
//                    		new CarDetectorServerWP("192.168.22.234", 964 ).startConnectService();
//                    		new CarDetectorServerWP("192.168.22.234", 965 ).startConnectService();
						}
						
					} catch (NumberFormatException e) {
						e.printStackTrace();
					}
                } catch (IOException e) {
                    LOG.error("启动车检仪Server失败, e: {}", e);
                }
            };
        };
        carTcpThread.start();
        BACKGROUND_THREADS.put(CAR_TCP_THREAD_ALIAS, carTcpThread);
       
    }
    
    @Override
    public void initAllScreen() {
        Thread allScreenThread = new Thread(INIT_ALLSCREEN_THREAD_NAME) {
            public void run() {
                cameraControlLogic.saveAllScreensByTwallCode(null);// 同步大屏列表
                GlobalInitLogicImpl.INIT_ALLSCREEN_START_UP  = true;//标识大屏初始化成功
            };
        };
        allScreenThread.start();
        BACKGROUND_THREADS.put(INIT_ALLSCREEN_THREAD_ALIAS, allScreenThread);
    }
    
    @Override
	public void initNDFireService() {
    	 FireHandler fireHandler=new FireHandler();
 		 fireHandler.alarmMethod();
	}
    
    @Override
    public void initDataBase() {
        Thread initDataBaseThread = new Thread(INIT_DATABASE_THREAD_NAME) {
            private int count = 3;
            private String messgae;
            public void run() {
                while (count > 0) {
                    Jedis redis = null;
                    try {
                        // 检查初始化数据是否存在
                        initDataBaseDao.newDatabaseCheck();
                        count = 0;
                        break;
                    } catch (DataAccessException e) {
                        if (e.getCause() instanceof SQLException) {
                            SQLException se = (SQLException) e.getCause();
                            if ("42S02".equals(se.getSQLState())) {
                                LOG.debug("检查数据库表不存在,需要执行初始化操作");
                                // 检查数据不存在需要执行初始化操作
                                String url = PropertiesUtils.findPropertiesKey("jdbc.url");
                                String driver = PropertiesUtils.findPropertiesKey("jdbc.driverClass");
                                String username = PropertiesUtils.findPropertiesKey("jdbc.user");
                                String password = PropertiesUtils.findPropertiesKey("jdbc.password");
                                Connection conn = null;
                                try {
                                    Class.forName(driver).newInstance();
                                    conn = (Connection) DriverManager.getConnection(url, username, password);
                                    ScriptRunner runner = new ScriptRunner(conn);
                                    runner.setErrorLogWriter(null);
                                    runner.setLogWriter(null);
                                    runner.runScript((new InputStreamReader(
                                            CommonUtils.class.getClassLoader().getResourceAsStream("init.sql"), "UTF-8")));
                                    GlobalInitLogicImpl.INIT_DATABASE_START_UP = true;//标识数据库初始化成功
                                } catch (UnsupportedEncodingException e1) {
                                    LOG.error("initializeDataBase UnsupportedEncodingException ERROR \r\n", e);
                                    messgae = CommonUtils.ERROR_MSG;
                                } catch (SQLException e1) {
                                    LOG.error("initializeDataBase SQLException ERROR \r\n", e1);
                                    messgae = CommonUtils.ERROR_MSG;
                                } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e2) {
                                    LOG.error("initializeDataBase InstantiationException ERROR \r\n", e2);
                                    messgae = CommonUtils.ERROR_MSG;
                                } finally {
                                    try {
                                        conn.close();
                                    } catch (SQLException e1) {
                                        LOG.error("initializeDataBase connClose ERROR \r\n", e1);
                                    }
                                }
                                List<String> codes = initDataBaseDao.selectInitCodes();
                                redis = redisPool.getResource();
                                redis.select(Integer.parseInt(PropertiesUtils.findPropertiesKey("redis.db.code")));
                                for (String code : codes) {
                                    if (code.substring(0, 2).equals(RESOURCE_CODE)) {
                                        redis.sadd(RESOURCE_NAME, code);
                                    } else if (code.substring(0, 2).equals(ROLE_CODE)) {
                                        redis.sadd(ROLE_NAME, code);
                                    } else if (code.substring(0, 2).equals(USER_CODE)) {
                                        redis.sadd(USER_NAME, code);
                                    } else if (code.substring(0, 2).equals(CUSTOMER_CODE)) {
                                        redis.sadd(CUSTOMER_NAME, code);
                                    }
                                }
                                messgae = CommonUtils.SUCCESS_MSG;
                            }
                        }
                    } finally {
                        redisPool.returnResource(redis);
                    }
                }
                count--;
            };
        };
        initDataBaseThread.start();
        BACKGROUND_THREADS.put(INIT_DATABASE_THREAD_ALIAS, initDataBaseThread);
    }
    
    @Override
	public void initPlanScanThread() {
		// TODO Auto-generated method stub
    	LOG.info("群控联动扫描启动------------------------------------------------------------");
		try {
			 
			Thread initPlanScan= new Thread(INIT_PLAN_SCAN_NAME){
				public void run(){
					
					SchduleScanJob a = new SchduleScanJob();
					a.execute(); 
					
					//监测电力数据欠压,过压,过载的线程
					ElectricInformationScanJob eis = new ElectricInformationScanJob();
					eis.execute();
					
					//监测电力数据断路,短路的线程
					ElectricMonitor em = new ElectricMonitor();
					em.execute();
				}
			};
			initPlanScan.start();
			BACKGROUND_THREADS.put(INIT_PLAN_SCAN_ALIAS, initPlanScan);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    
    
    @PostConstruct
    public void contextInit() {
        initEmergecyPhoneRevice();//紧急电话启动
        initFireCRERevice();//火灾告警器启动
        initCarTcpRevice();//车检仪启动
        initAllScreen();//大屏初始化启动
        initLightTcpService();
        initPlanScanThread();
        initDataBase();//数据库初始化启动
        LOG.debug("全局启动成功");
    }
	 
}
